<template>
  <div class="home">
    <!-- 按钮集合 -->
    <section class="buttons">
      <p
        style="
          font-size: 12px;
          color: #4f4f4f;
          margin-left: 15px;
          cursor: pointer;
        "
        @click="Previous"
      >
        <!-- 返回 -->
      </p>
      <div>
        <!-- <el-button @click="reloads" type="danger"
          ><i class="el-icon-delete-solid el-icon--left"></i>重置</el-button
        > -->
        <!--
        <el-button @click="catJson">查看JSON </el-button>
        <el-button @click="$refs.file.click()">导入JSON </el-button>
        <el-button @click="exportJSON">导出JSON </el-button> -->
        <!-- <input
          type="file"
          ref="file"
          id="file"
          accept=".json"
          @change="importJSON"
          style="display: none"
        /> -->
        <!-- <el-button @click="Preservation"
          ><i class="el-icon-s-claim el-icon--left"></i>保存</el-button
        > -->
      </div>
    </section>
    <!-- 装修操作 -->
    <section class="operation">
      <!-- 组件 -->
      <sliderassembly :pointer="pointer" />
      <!-- 中间预览 -->
      <div
        class="phone"
        style="
          border: 2px solid red;
          display: flex;
          flex-direction: column;
          align-items: center;
        "
      >
        <!-- <el-button @click="catJson">查看JSON </el-button> -->

        <div class="preview-actions">
          <div class="">
            <button
              class="carousel-btn consult-btn"
              @click="realTimeView.show = true"
              style="padding: 5px 15px"
            >
              预览
            </button>
            <button class="carousel-btn consult-btn" style="padding: 5px 15px">
              保存
            </button>
            <button class="carousel-btn" style="padding: 5px 15px">发布</button>
          </div>
          <PublicNavBar
            :items="navbarList"
            direction="horizontal"
            :horizontalWidth="horizontalWidth"
            @handleItemClick="navbarClick"
            :activeIndex="activeNavbarIndex"
            :itemSpacingArray="[0, 40, 40, 40]"
          />
        </div>
        <div style="border: 2px solid green;position: relative;">
          <div
            class="phoneAll"
            ref="imageTofile"
            id="imageTofile"
            style="border: 2px solid blue"
          >
            <img src="@/assets/images/phoneTop.png" alt="" class="statusBar" />
            <!-- 头部导航 -->
            <headerTop :pageSetup="pageSetup" @click.native="headTop" />
            <!-- 主体内容 -->
            <section
              class="phone-container"
              :style="{
                'background-color': pageSetup.bgColor,
                backgroundImage: 'url(' + pageSetup.bgImg + ')',
              }"
              @drop="drop($event)"
              @dragover="allowDrop($event)"
              @dragleave="dragleaves($event)"
            >
              <div :class="pointer.show ? 'pointer-events' : ''">
                <!-- 动态组件 -->
                <component
                  :is="item.component"
                  v-for="(item, index) in pageComponents"
                  :key="index"
                  :datas="item.setStyle"
                  :style="{
                    border: item.active && deleShow ? '2px solid #155bd4' : '',
                  }"
                  @click.native="activeComponent(item, index)"
                  class="componentsClass"
                  :data-type="item.type"
                >
                 <!-- 删除组件 -->
                  <!-- <div
                    v-show="deleShow"
                    class="deles"
                    slot="deles"
                    @click.stop="deleteObj(index)"
                  >
                   
                    <span class="iconfont icon-sanjiaoxingzuo"></span>
                    {{ item.text }}
                    <i class="el-icon-delete-solid" />
                  </div> -->
                </component>
              </div>
            </section>

            <!-- 手机高度 -->
            <div class="phoneSize">iPhone 8手机高度</div>
          </div>
          <div class="delete" style="background-color: red;position: absolute;top: 0;right: -70px;">
            删除组件
          </div>
           <!-- 底部 -->
           <div class="" style="border: 2px solid red;margin-top: -17px;">
              <phoneBottom />
            </div>
        </div>

        <!-- 底部 -->
      </div>
      <!-- 页面设置tab -->
      <!-- <div class="decorateTab">
        <span
          :class="rightcom === 'decorate' ? 'active' : ''"
          @click="rightcom = 'decorate'"
        >
          <i class="iconfont icon-wangye" />
          页面设置
        </span>
        <span
          :class="rightcom === 'componenmanagement' ? 'active' : ''"
          @click="rightcom = 'componenmanagement'"
        >
          <i class="iconfont icon-zujian" />
          组件管理
        </span>
        <span
          class="active"
          v-show="rightcom != 'componenmanagement' && rightcom != 'decorate'"
        >
          <i class="iconfont icon-zujian" />
          组件设置
        </span>
      </div> -->
      <!-- 右侧工具栏 -->
      <div class="decorateAll">
        <!-- 页面设置 -->
        <!-- <transition name="decorateAnima"> -->
        <editFormheader :datas="currentproperties" />
        <!-- 动态组件 -->
        <component
          :is="rightcom"
          :datas="currentproperties"
          @componenmanagement="componenmanagement"
        />
        <!-- </transition> -->
      </div>
    </section>
    <!-- 实时预览 -->
    <realTimeView
      :datas="realTimeView"
      :val="{
        id,
        name: pageSetup.name,
        templateJson: JSON.stringify(pageSetup),
        component: JSON.stringify(pageComponents),
      }"
    />
  </div>
</template>

<script>
import editFormheader from "@/components/components/editFormheader";
// / 引用公共的导航栏组件
import PublicNavBar from "@/components/public/NavBar";
// 引用左侧基础组件sliderassembly
import sliderassembly from "@/components/components/sliderassembly";
//引用头部导航
import headerTop from "@/components/components/headerTop";
//引用底部导航
import phoneBottom from "@/components/components/phoneBottom";
import utils from "@/utils/index"; // 方法类
import componentProperties from "@/utils/componentProperties"; // 组件数据
import html2canvas from "html2canvas"; // 生成图片
import FileSaver from "file-saver"; // 导出JSON

export default {
  name: "home",
  inject: ["reload"],
  components: {
    sliderassembly,
    headerTop,
    phoneBottom,
    PublicNavBar,
    editFormheader,
  },
  data() {
    return {
      activeIndex: 0,
      activeNavbarIndex: 0,
      horizontalWidth: "63%",
      navbarList: [
        { label: "微官网", path: "" },
        { label: "PC端官网", path: "" },
      ],
      realTimeView: {
        show: false, // 是否显示预览
      },
      id: null, //当前页面
      deleShow: true, //删除标签显示
      index: "", //当前选中的index
      rightcom: "decorate", //右侧组件切换
      currentproperties: {}, //当前属性
      pageSetup: {
        // 页面设置属性
        name: "页面标题", //页面名称
        enterpriseName: "企业名称",
        customColor: "rgba(31, 241, 199, 1)", //自定义颜色
        details: "", //页面描述
        isPerson: false, // 是否显示个人中心
        isBack: true, // 是否返回按钮
        titleHeight: 35, // 高度
        bgColor: "rgba(249, 249, 249, 10)", //背景颜色
        bgImg: "", // 背景图片
      },
      pageComponents: [], //页面组件
      offsetY: 0, //记录上一次距离父元素高度
      pointer: { show: false }, //穿透
      onlyOne: ["1-5", "1-16"], // 只能存在一个的组件(组件的type)
    };
  },

  mounted() {
    this.pageSetup.name = "页面标题";
    this.currentproperties = this.pageSetup;
  },

  methods: {
    // 顶部导航栏切换回调
    navbarClick(obj) {
      this.activeNavbarIndex = obj.index;
      this.horizontalWidth = obj.index == 0 ? "63%" : "73%";
      console.log("打印", obj);
    },
    // 查看JSON
    catJson() {
      this.$alert(
        `{
          <br/>
          "id": ${this.id},
          <br/>
          "name": "${this.pageSetup.name}",
          <br/>
          "templateJson": '${JSON.stringify(this.pageSetup)}',
          <br/>
          "component": '${JSON.stringify(this.pageComponents)}',
          <br/>
        }`,
        "查看JSON",
        {
          confirmButtonText: "确定",
          customClass: "JSONView",
          dangerouslyUseHTMLString: true,
          callback: () => {},
        }
      );
    },
    /**
     * 保存
     */
    Preservation() {
      /* 隐藏border和删除图标 */
      this.deleShow = false;
      /* 渲染结束截图 */
      this.$nextTick(() => {
        /* 截图 */
        this.toImage();
      });
    },

    /**
     * 页面截图
     *
     * @param {Function} callBack 回调函数
     */
    toImage() {
      /* 加载 */
      const loading = this.$loading({
        lock: true,
        text: "保存中...",
        spinner: "el-icon-loading",
        background: "rgba(0, 0, 0, 0.7)",
      });

      const imageTofiles = document.querySelector("#imageTofile");
      /* 截图 */
      html2canvas(this.$refs.imageTofile, {
        backgroundColor: null,
        height: imageTofiles.scrollHeight,
        width: imageTofiles.scrollWidth,
        useCORS: true,
      }).then((canvas) => {
        /* 显示border和删除图标 */
        this.deleShow = true;
        let url = canvas.toDataURL("image/png");
        const formData = new FormData();
        formData.append("base64File", url);
        console.log(formData, "--------------页面图片formData");
        loading.close();
      });
    },

    /**
     * 当将元素或文本选择拖动到有效放置目标（每几百毫秒）上时，会触发此事件
     *
     * @param {Object} event event对象
     */
    allowDrop(event) {
      //阻止浏览器的默认事件
      event.preventDefault();

      /* 获取鼠标高度 */
      let eventoffset = event.offsetY;

      /* 如果没有移动不触发事件减少损耗 */
      if (this.offsetY === eventoffset) return;
      else this.offsetY = eventoffset;

      /* 获取组件 */
      const childrenObject = event.target.children[0];

      // 一个以上的组件计算
      if (this.pageComponents.length) {
        /* 如果只有一个组件并且第一个是提示组件直接返回 */
        if (
          this.pageComponents.length === 1 &&
          this.pageComponents[0].type === 0
        )
          return;

        /* 如果鼠标的高度小于第一个的一半直接放到第一个 */
        if (eventoffset < childrenObject.children[0].clientHeight / 2) {
          /* 如果第一个是提示组件直接返回 */
          if (this.pageComponents[0].type === 0) return;

          /* 删除提示组件 */
          this.pageComponents = this.pageComponents.filter(
            (res) => res.component !== "placementarea"
          );

          /* 最后面添加提示组件 */
          this.pageComponents.unshift({
            component: "placementarea",
            type: 0,
          });

          return;
        }

        /* 记录距离父元素高度 */
        const childOff = childrenObject.offsetTop;

        /* 鼠标在所有组件下面 */
        if (
          eventoffset > childrenObject.clientHeight ||
          childrenObject.lastChild.offsetTop -
            childOff +
            childrenObject.lastChild.clientHeight / 2 <
            eventoffset
        ) {
          /* 最后一个组件是提示组件返回 */
          if (this.pageComponents[this.pageComponents.length - 1].type === 0)
            return;

          /* 清除提示组件 */
          this.pageComponents = this.pageComponents.filter(
            (res) => res.component !== "placementarea"
          );

          /* 最后一个不是提示组件添加 */
          this.pageComponents.push({
            component: "placementarea",
            type: 0,
          });

          return;
        }

        const childrens = childrenObject.children;

        /* 在两个组件中间，插入 */
        for (let i = 0, l = childrens.length; i < l; i++) {
          const childoffset = childrens[i].offsetTop - childOff;

          if (childoffset + childrens[i].clientHeight / 2 > event.offsetY) {
            /* 如果是提示组件直接返回 */
            if (this.pageComponents[i].type === 0) break;

            if (this.pageComponents[i - 1].type === 0) break;

            /* 清除提示组件 */
            this.pageComponents = this.pageComponents.filter(
              (res) => res.component !== "placementarea"
            );

            this.pageComponents.splice(i, 0, {
              component: "placementarea",
              type: 0,
            });
            break;
          } else if (childoffset + childrens[i].clientHeight > event.offsetY) {
            if (this.pageComponents[i].type === 0) break;

            if (
              !this.pageComponents[i + 1] ||
              this.pageComponents[i + 1].type === 0
            )
              break;

            this.pageComponents = this.pageComponents.filter(
              (res) => res.component !== "placementarea"
            );

            this.pageComponents.splice(i, 0, {
              component: "placementarea",
              type: 0,
            });

            break;
          }
        }
      } else {
        /* 一个组件都没有直接push */
        this.pageComponents.push({
          component: "placementarea",
          type: 0,
        });
      }
    },

    /**
     * 当在有效放置目标上放置元素或选择文本时触发此事件
     *
     * @param {Object} event event对象
     */
    drop(event) {
      /* 获取数据 */
      let data = utils.deepClone(
        componentProperties.get(event.dataTransfer.getData("componentName"))
      );

      /* 查询是否只能存在一个的组件且在第一个 */
      let someOne = this.pageComponents.some((item, index) => {
        return (
          item.component === "placementarea" &&
          index === 0 &&
          this.onlyOne.includes(data.type)
        );
      });
      if (someOne) {
        this.$message.info("固定位置的组件(如: 底部导航、悬浮)不能放在第一个!");
        /* 删除提示组件 */
        this.dragleaves();
        return;
      }

      /* 查询是否只能存在一个的组件 */
      let someResult = this.pageComponents.some((item) => {
        return (
          this.onlyOne.includes(item.type) &&
          item.component === event.dataTransfer.getData("componentName")
        );
      });
      if (someResult) {
        this.$message.info("当前组件只能添加一个!");
        /* 删除提示组件 */
        this.dragleaves();
        return;
      }

      /* 替换 */
      utils.forEach(this.pageComponents, (res, index) => {
        /* 修改选中 */
        if (res.active === true) res.active = false;
        /* 替换提示 */
        this.index = index;
        if (res.component === "placementarea")
          this.$set(this.pageComponents, index, data);
      });

      /* 切换组件 */
      this.rightcom = data.style;
      /* 丢样式 */
      this.currentproperties = data.setStyle;

      console.log(
        data,
        this.rightcom,
        this.currentproperties,
        "----------components data"
      );
    },

    /**
     * 当拖动的元素或文本选择离开有效的放置目标时，会触发此事件
     *
     * @param {Object} event event对象
     */
    dragleaves() {
      /* 删除提示组件 */
      this.pageComponents = this.pageComponents.filter(
        (res) => res.component !== "placementarea"
      );
    },

    /**
     * 切换组件位置
     *
     * @param {Object} res 组件切换后返回的位置
     */
    componenmanagement(res) {
      this.pageComponents = res;
    },

    /**
     * 选择组件
     *
     * @param {Object} res 当前组件对象
     */
    activeComponent(res, index) {
      this.index = index;
      /* 切换组件 */
      this.rightcom = res.style;
      /* 丢样式 */
      this.currentproperties = res.setStyle;

      /* 替换 */
      utils.forEach(this.pageComponents, (res) => {
        /* 修改选中 */
        if (res.active === true) res.active = false;
      });

      /* 选中样式 */
      res.active = true;
    },

    /**
     * 标题切换
     *
     * @param {Object} res 当前组件对象
     */
    headTop() {
      this.rightcom = "decorate";

      /* 替换 */
      utils.forEach(this.pageComponents, (res) => {
        /* 修改选中 */
        if (res.active === true) res.active = false;
      });
    },

    /* 删除组件 */
    deleteObj(index) {
      this.pageComponents.splice(index, 1);
      if (this.index === index) this.rightcom = "decorate";
      if (index < this.index) this.index = this.index - 1;
    },

    /* 页面刷新 */
    reloads() {
      this.$confirm("重置后您添加或者修改的数据将会失效, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.reload();
        })
        .catch(() => {});
    },

    // 返回上一步
    Previous() {
      this.$confirm("返回列表您添加或者修改的数据将会失效, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.$router.go(-1);
        })
        .catch(() => {});
    },

    // 导出json
    exportJSON() {
      // 将json转换成字符串
      const data = JSON.stringify({
        id: this.id,
        name: this.pageSetup.name,
        templateJson: JSON.stringify(this.pageSetup),
        component: JSON.stringify(this.pageComponents),
      });
      const blob = new Blob([data], { type: "" });
      FileSaver.saveAs(blob, `${this.pageSetup.name}.json`);
    },
    // 导入json
    importJSON() {
      const file = document.getElementById("file").files[0];
      const reader = new FileReader();
      reader.readAsText(file);
      let _this = this;
      reader.onload = function () {
        // this.result为读取到的json字符串，需转成json对象
        let ImportJSON = JSON.parse(this.result);
        // 检测是否导入成功
        console.log(ImportJSON, "-----------------导入成功");
        // 导入JSON数据
        _this.id = ImportJSON.id;
        _this.pageSetup = JSON.parse(ImportJSON.templateJson);
        _this.pageComponents = JSON.parse(ImportJSON.component);
      };
    },
  },

  watch: {
    /* 监听右侧属性设置切换 */
    rightcom(newval) {
      if (newval === "decorate") {
        utils.forEach(this.pageComponents, (res) => {
          /* 修改选中 */
          if (res.active === true) res.active = false;
        });
        this.currentproperties = this.pageSetup;
        return;
      }
      if (newval === "componenmanagement") {
        /* 替换 */
        utils.forEach(this.pageComponents, (res) => {
          /* 修改选中 */
          if (res.active === true) res.active = false;
        });
        this.currentproperties = this.pageComponents;
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.pointer-events {
  pointer-events: none;
}

.home {
  width: 100%;
  height: 100%;

  /* 删除组件 */
  .deles {
    position: absolute;
    min-width: 80px;
    text-align: center;
    line-height: 25px;
    background: #fff;
    height: 25px;
    font-size: 12px;
    left: 103%;
    top: 50%;
    transform: translateY(-50%);
    .icon-sanjiaoxingzuo {
      position: absolute;
      left: -11px;
      color: #fff;
      font-size: 12px;
      top: 50%;
      transform: translateY(-50%);
    }
    &:hover {
      i {
        display: block;
        position: absolute;
        left: 0;
        font-size: 16px;
        top: 0;
        text-align: center;
        line-height: 25px;
        width: 100%;
        color: #fff;
        height: 100%;
        z-index: 10;
        background: rgba(0, 0, 0, 0.5);
      }
      .icon-sanjiaoxingzuo {
        color: rgba(0, 0, 0, 0.5);
      }
    }

    i {
      display: none;
    }
  }

  /* 按钮集合 */
  .buttons {
    height: 8%;
    border-bottom: 1px solid #ebedf0;
    display: flex;
    justify-content: space-between;
    box-sizing: border-box;
    padding-right: 15px;
    align-items: center;
    /* 下拉 */
    .frop {
      padding-right: 15px;
      .el-button.el-button--primary.el-dropdown-selfdefine {
        background: #fff;
        color: #000;
        border: 1px solid #dcdee0;
      }
    }
    .el-button {
      font-size: 14px;
      padding: 0 16px;
      height: 30px;
      &.el-button--primary {
        background: #155bd4;
      }
      &.el-button--danger {
        background: red;
      }
    }
  }

  /* 操作主体 */
  .operation {
    width: 100%;
    height: calc(100vh - 65px);
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    background: #f7f8fa;
  }
  .preview-actions {
    padding-top: 20px;
    // text-align: center;
    // margin-top: 120px;
  }

  /* 手机 */
  .phone {
    width: 55%;
    height: 100%;
    // overflow-y: scroll;
    display: flex;
    justify-content: center;
    background: #f7f8fa;
    &::-webkit-scrollbar {
      width: 1px;
    }
    // &::-webkit-scrollbar-thumb {
    //   background-color: #155bd4;
    // }

    /* 手机样式 */
    .phoneAll {
      width: 375px;
      height: 400px;
      height: calc(100vh - 250px);
      overflow: scroll;
      &::-webkit-scrollbar {
        //隐藏原生滚动轴
        width: 1px;
      }
      // min-height: 760px;
      box-shadow: 0 0 14px 0 rgba(0, 0, 0, 0.1);
      margin: 15px 0 0 0;
      position: relative;
      padding-bottom: 50px;

      /* 手机高度 */
      .phoneSize {
        position: absolute;
        left: -137px;
        top: 640px;
        font-size: 12px;
        color: #a2a2a2;
        border-bottom: 1px solid #dedede;
        width: 130px;
        height: 21px;
        line-height: 21px;
      }
      .phoneBottom {
        border: 3px solid red;
        margin-top: -30px;
        
        // position: absolute;
        // left: -137px;
        // top: 660px;
        // font-size: 12px;
        // color: #a2a2a2;
        // border-bottom: 1px solid #dedede;
        // width: 130px;
        // height: 21px;
        // line-height: 21px;
      }

      /* 状态栏 */
      .statusBar {
        width: 100%;
        display: block;
      }

      /* 主体内容 */
      .phone-container {
        min-height: 367px;
        box-sizing: border-box;
        cursor: pointer;
        width: 100%;
        position: relative;
        background-repeat: no-repeat;
        background-size: 100% 100%;
        .componentsClass {
          border: 1px solid #fff;
          &:hover {
            border: 1px dashed #155bd4;
          }
        }
      }
    }
  }

  /* 右侧工具栏 */
  .decorateAll {
    border: 3px solid green;
    width: 376px;
    height: 100%;
    // height: calc(100vh - 60px);
    overflow-y: scroll;
    overflow-x: hidden;
    position: relative;
    padding: 0 12px;
    background: #fff;
    &::-webkit-scrollbar {
      width: 1px;
    }
    &::-webkit-scrollbar-thumb {
      background-color: #155bd4;
    }
  }

  /* 页面设置tab */
  .decorateTab {
    position: fixed;
    display: flex;
    right: 380px;
    top: 115px;
    flex-direction: column;
    span {
      background-color: #fff;
      box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
      border-radius: 2px;
      width: 94px;
      height: 32px;
      display: inline-block;
      text-align: center;
      line-height: 32px;
      margin-bottom: 12px;
      transition: all 0.8s;
      cursor: pointer;
      &.active {
        background-color: #155bd4;
        color: #fff;
      }
      /* 图标 */
      i {
        font-size: 12px;
        margin-right: 5px;
      }
    }
  }
}

/* 动画 */
.decorateAnima-enter-active {
  transition: all 1.5s ease;
}
.decorateAnima-leave-active {
  transition: all 1.5s ease;
}
.decorateAnima-enter {
  transform: translate(8px, 8px);
  opacity: 0;
}
.decorateAnima-leave-to {
  transform: translate(8px, 8px);
  opacity: 0;
}
</style>
